#ifndef _SIMMODELS
#define _SIMMODELS
#include <string>
using namespace std;

#include "SimMgmt.h"
using namespace SimMgmt;

#include "Card.h"
#include "Action.h"

namespace SimModels {
/*
   class SpeakMsg : public Message 
   {  // Inherits from Message
   
      public:
          SpeakMsg(int Handler, string Description, string Speak);
         ~SpeakMsg() { }
          string getContent() const { return content; }
 
	  protected:
          //Inherited as virtual and must be redefined:
		  virtual void Insert(); //Must write to the default program output stream
          virtual void Put();    //Must write to the default program output stream
      
      private:
          string content;
   };  //SpeakMsg 
*/
   class CardMsg : public Message 
   {  // Inherits from Message
   
      public:
		  CardMsg(int Handler, string Description, Card::Suit cardsuit,  int cardvalue);
         ~CardMsg() { }
		 //These two methods had to be added so the AcceptCard method could figure out what suit
		 //and value the card has.
		 Card::Suit getSuit() const { return cardsuitmsg; }
		  int  getValue() const { return cardvaluemsg; }
 
	  protected:
          //Inherited as virtual and must be redefined:
		  virtual void Insert(); //Must write to the default program output stream
          virtual void Put();    //Must write to the default program output stream
      
      private:
		 Card::Suit cardsuitmsg;
		 int   cardvaluemsg;
   };  //CardMsg

   class ActionMsg : public Message 
   {  // Inherits from Message
   
      public:
		  ActionMsg(int Handler, string Description, Action::Choice typeofaction);
         ~ActionMsg() { }
		 Action::Choice getChoice() const{ return decision;}
		 
		 //string getContent() const { return content; }
 
	  protected:
          //Inherited as virtual and must be redefined:
		  virtual void Insert(); //Must write to the default program output stream
          virtual void Put();    //Must write to the default program output stream
      
      private:
		  Action::Choice decision;
          string content;
   };  //ActionMsg

   class Players : public Message 
   {  // Inherits from Message
      public:
         Players(int MaxAgents) throw(AppError);
         ~Players();
		 int       getNumAgents();
         AGENTPTR  getAgent(string playerid) throw(AppError);
		 AGENTPTR  getDealer() throw(AppError);
		 AGENTPTR  *getGamblers()throw(AppError);
         AGENTPTR  *getOthers(int Num) throw(AppError);
         void      setAgent(string playerid, AGENTPTR agent) throw(AppError);
		 void      setDealer(AGENTPTR agent) throw(AppError);
	  protected:
          //Inherited as virtual and must be redefined:
		  virtual void Insert();//Must write to the default program output stream
          virtual void Put();   //Must write to the default program output stream
      private:
         int      numAgents;
		 int      lastAgent;
         AGENTPTR *agents;
		 AGENTPTR dealerptr;
         string   *agentNames;
   }; //Players
/*
   class Student : public Agent 
   {  // Inherits from Agent
      public:
         Student();
         ~Student();
         void Initialize(MSGPTR players);
         void Dispatch  (MSGPTR msg);
         SpeakMsg *AcceptQuestion(string aquestion);
         SpeakMsg *AcceptAnswer  (string response);
		 Message  *AcceptTerminate();
		 Message  *AcceptScanComplete();
		 virtual void Extract() throw(TokenError);
		 virtual void Insert();

      protected:
		 virtual void Get()     throw(TokenError);
         virtual void Put();
       
      private:
         void doQuestions(string question);
         void doAnswers  (string answer);
		 void doTerminate();
		 void doScanComplete();
         Student  *me;
		 AGENTPTR *you;
		 int lastyou;
         int ansrDelay;
		 int questDelay;
		 int scanDelay;
		 int interest;
   }; //Student
*/
   class Dealer : public Agent 
   {  // Inherits from Agent
      public:
         Dealer();
         ~Dealer();
         void Initialize(MSGPTR players);
         void Dispatch  (MSGPTR msg);
        // SpeakMsg *AcceptQuestion(string card1);
        // SpeakMsg *AcceptAnswer  (string gAct);
		 CardMsg  *AcceptCard(Card::Suit mysuit, int value);
         Message  *AcceptTurn();
		 ActionMsg *AcceptDealerAction(Action::Choice dAct);
		 ActionMsg *AcceptGamblerAction(Action::Choice gAct);
		 Message  *AcceptStartComplete();
		 Message  *AcceptTerminate();
		 Message  *AcceptEndGame();
		 Message  *CardReceivedMsg();

		 virtual void Extract() throw(TokenError);
		 virtual void Insert();
		 int GetUpCard(){return hand[0].GetCardValue();}

      protected:
		 virtual void Get()     throw(TokenError);
         virtual void Put();
       
      private:
		 void doAcceptCard(int value, Card::Suit mysuit);
         void doAcceptTurn();
         void doQuestions(string question);
         void doAnswers  (string answer);
		 void doEndGame();
		 void doTerminate();
		 void doStartComplete();
		 void doCardReceived();
		 void doPlayerAction(Action::Choice theirchoice);
		 void doDealerAction(Action::Choice mychoice);
		 void getShuffledDeck();

         Dealer  *me;
		 AGENTPTR *you;
		 AGENTPTR *gamblers2;
		 int lastyou;
         int ansrDelay;
		 int dealerStrategy;//NEW
		 int startDelay;
		
		 int numGamblers;
		 int currentCard;
		 int dealOrder[52];
		 Card deck[52];
		 int interest;
		 Card hand[11];
		 int numCards;
		 int numEndGames;
		 int currentGambler;
		 int numSims;
		 int cardvalue[11];
		 int totalvalue;
		 int flag[11];
   }; //Dealer

   class Gambler : public Agent 
   {  // Inherits from Agent
      public:
         Gambler();
         ~Gambler();
         void Initialize(MSGPTR players);
         void Dispatch  (MSGPTR msg);
		 CardMsg  *AcceptCard(Card::Suit mysuit, int value);
         Message  *AcceptTurn();
		 Message  *AcceptTerminate();
		 Message  *AcceptStartComplete();
		 Message  *AcceptEndGame();
		 virtual void Extract() throw(TokenError);
		 virtual void Insert();

      protected:
		 virtual void Get()     throw(TokenError);
         virtual void Put();
       
      private:
		 void doAcceptCard(int value, Card::Suit mysuit);
         void doAcceptTurn();
		 void doTerminate();
		 void doStartComplete();
		 void doEndGame();
         Gambler  *me;
		 AGENTPTR *you;
		 Dealer *dealer2;
		 int lastyou;
         int ansrDelay;
		 int playerStrategy[10][26];
		 int startDelay;
		 int interest;
		 Card hand[11];
		 Action::Choice decision;
		 int numCards;
		 int cardvalue[11];
		 int totalvalue;
		 int flag[11];
   }; //Gambler
/*
   class Conversation 
   {  //Virtual World
      public:
         Conversation();
         ~Conversation();
         void Initialize();
         void Simulate();
         void WrapUp(); //Writes to the default program output stream
         void Insert();    //Writes to the default program output stream
		 
      
      private:
	     int       numStudents;
		 int	   numGamblers;//This will be used when Conversation changes to BlackJack
		 int	   numEvents;
		 int	   lastEvent;	
	     AGENTPTR  *students; //dynamic array of Agent*
		 
		 //pointer to Dealer
		 //This will be used when Conversation changes to BlackJack
		 AGENTPTR  dealer;
		 
		 //dynamic array of Gamblers
		 //This will be used when Conversation changes to BlackJack
		 AGENTPTR  *gamblers;
   };//Conversation
*/
   class Blackjack 
   {  //Virtual World
      public:
         Blackjack();
         ~Blackjack();
         void Initialize();
         void Simulate();
         void WrapUp(); //Writes to the default program output stream
         void Insert();    //Writes to the default program output stream
      
      private:
		 int	   numGamblers;//This will be used when Conversation changes to BlackJack
		 int	   numEvents;
		 int	   lastEvent;

   };//Blackjack
	     Gambler  *gamblers; //dynamic array of Agent*
		 Dealer  dealer; //Agent* for Dealer

   //Gambler* gamblerStore;
   //Dealer	dealerStore;
}//SimModels
#endif